package com.ruicar.afs.cloud.product.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.log.annotation.SysLog;
import com.ruicar.afs.cloud.common.core.query.QueryCondition;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.uid.AfsSequenceGenerator;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.product.condition.ProductPlanCondition;
import com.ruicar.afs.cloud.product.condition.ProductUpdateCondition;
import com.ruicar.afs.cloud.product.condition.ProductUpdatePlanCondition;
import com.ruicar.afs.cloud.product.condition.ProductUpdateSaveCondition;
import com.ruicar.afs.cloud.product.entity.*;
import com.ruicar.afs.cloud.product.enums.ProductOnlineStatus;
import com.ruicar.afs.cloud.product.enums.StatusType;
import com.ruicar.afs.cloud.product.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.product.service.*;
import com.ruicar.afs.cloud.product.vo.ProductPlanInfoVo;
import com.ruicar.afs.cloud.product.vo.ProductUpdatePlanVo;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.WorkFlowResponse;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.QueryFLowCmdRequest;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.TaskSubmitRequest;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.response.FlowCmdBean;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author xudongdong
 * @version 1.0
 * @date 2020-05-22
 */
@Slf4j
@RestController
@AllArgsConstructor
@Api("产品方案接口")
@RequestMapping("/productUpdatePlan")
public class ProductUpdatePlanController {

    private final ProductPlanService productPlanService;
    private final ProductUpdateService productUpdateService;
    private final ProductUpdatePlanService productUpdatePlanService;
    private final ProductUpdateAtomService productUpdateAtomService;
    private final ProductUpdateRepayService productUpdateRepayService;
    private final ProductUpdateRateService productUpdateRateService;
    private final LprConfigurationService lprService;
    //工作流
    private final WorkflowService workflowService;
    private final WorkTaskCreatedService workTaskCreatedService;
    private final WorkTaskAssignService workTaskAssignService;
    private final WorkApproveRecordService workApproveRecordService;

    private final AfsSequenceGenerator afsSequenceGenerator;

    @PostMapping(value = "/getApprovePlanList")
    @ApiOperation(value = "产品方案修改代办任务")
    public IResponse getApprovePlanList(@RequestBody QueryCondition<ProductUpdateCondition> planCondition) {
        IPage<List<ProductUpdate>> list = productUpdateService.page(new Page(planCondition.getPageNumber(), planCondition.getPageSize()), Wrappers.<ProductUpdate>query().lambda()
                .eq(StringUtils.isNotEmpty(planCondition.getCondition().getStatus()), ProductUpdate::getStatus, planCondition.getCondition().getStatus())//状态
                .like(StringUtils.isNotEmpty(planCondition.getCondition().getPlanNumber()), ProductUpdate::getPlanNumber, planCondition.getCondition().getPlanNumber())
                .like(StringUtils.isNotEmpty(planCondition.getCondition().getPlanName()), ProductUpdate::getPlanName, planCondition.getCondition().getPlanName())
                .eq(planCondition.getCondition().getEffectiveDate()!=null, ProductUpdate::getEffectiveDate, planCondition.getCondition().getEffectiveDate())
                .orderByDesc(ProductUpdate::getCreateTime)
        );
        return new IResponse().success(list);
    }


    @RequestMapping(value = "/getPrototypeInfo", method = RequestMethod.GET)
    @ApiOperation(value = "获取产品修改信息数据")
    public IResponse<ProductPlanInfoVo> queryProductPlanList(@ModelAttribute ProductPlanCondition planCondition) {
        ProductPlanInfoVo vo = new ProductPlanInfoVo();
        //获取原子参数值
        Map map = productUpdateAtomService.getProductPlanDataInfo(planCondition);
        vo.setJson(map);
        vo.setRateType((String) map.get("rateType"));//获取利率类型
        vo.setRepaymentType((String) map.get("repaymentType"));//获取还款方式
        vo.setIsAddLoan((String) map.get("isAddLoan"));
        vo.setDiscountType((String) map.get("discountType"));
        vo.setIsRiskPricing((String) map.get("isRiskPricing"));

        //获取基本信息
        ProductUpdate plan = productUpdateService.getById(planCondition.getId());
        vo.setProductUpdate(plan);

        //还款方式
        ProductUpdateRepay method = productUpdateRepayService.getOne(Wrappers.<ProductUpdateRepay>query().lambda()
                .eq(ProductUpdateRepay::getProductUpdateId, plan.getId()), false
        );
        if (method != null) {
            JSONObject object = JSONObject.parseObject(StringUtils.isEmpty(method.getRepaymentMethodData()) ? "{}" : method.getRepaymentMethodData());
            vo.setMethodParametersForm(object);
        }
        //利率
        List<ProductUpdateRate> list = productUpdateRateService.list(Wrappers.<ProductUpdateRate>query().lambda()
                .eq(ProductUpdateRate::getProductUpdateId, planCondition.getId())
        );
        //浮动利率时，利率重新获取
        if (AfsEnumUtil.key(StatusType.FLOAT).equals(vo.getRateType())) {
            List<ProductUpdateRate> listNew = new ArrayList<>();
            for (ProductUpdateRate productRate : list) {
                Double lprRate = lprService.getLprNew(productRate.getLoanPeriodStart(),productRate.getLoanPeriodEnd());
                productRate.setClearRate(productRate.getAddPointValue().divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(lprRate)));
                listNew.add(productRate);
            }
            list = listNew;
        }
        vo.setProductUpdateRates(list);
        return IResponse.success(vo);
    }

    @PostMapping("/saveProductProposal")
    @ApiOperation(value = "保存产品修改信息")
    @SysLog("保存产品方案")
    @Transactional(rollbackFor = Exception.class)
    public IResponse saveProductProposal(@RequestBody ProductUpdateSaveCondition prototypeCondition) {

        //修改方案
        ProductUpdate productUpdate = prototypeCondition.getProductPlan();
        if(StringUtils.isEmpty(productUpdate.getPlanNumber())){
            //获取编号
            Long seqno = afsSequenceGenerator.genNext(AfsEnumUtil.key(StatusType.PRODUCT_NUM_FAXG), StatusType.PRODUCT_NUM_FAXG.toString());
            String planNo = AfsEnumUtil.key(StatusType.PRODUCT_NUM_FAXG) + DateUtil.year(DateUtil.date()) +StringUtils.leftPad(String.valueOf(seqno), 4, '0');// 编号
            productUpdate.setPlanNumber(planNo);
        }
        productUpdate.setStatus(AfsEnumUtil.key(StatusType.TOSUBMIT));
        productUpdateService.saveOrUpdate(productUpdate);

        //修改原子
        productUpdateAtomService.remove(Wrappers.<ProductUpdateAtom>query().lambda()
                .eq(ProductUpdateAtom::getProductUpdateId,productUpdate.getId())
        );
        productUpdateAtomService.saveOrUpdate(prototypeCondition.getJson(), productUpdate.getId());
        //修改还款方式
        ProductUpdateRepay method = productUpdateRepayService.getOne(Wrappers.<ProductUpdateRepay>query().lambda().eq(ProductUpdateRepay::getProductUpdateId, productUpdate.getId()), false);
        if (method != null && prototypeCondition.getMethodParametersForm() != null) {
            method.setRepaymentMethod(prototypeCondition.getRepaymentMethod());
            method.setRepaymentMethodData(prototypeCondition.getMethodParametersForm().toString());
            productUpdateRepayService.updateById(method);
        } else if (method != null && prototypeCondition.getMethodParametersForm() == null) {
            productUpdateRepayService.removeById(method.getId());
        } else if (method == null && prototypeCondition.getMethodParametersForm() != null) {
            method = new ProductUpdateRepay();
            method.setProductUpdateId(productUpdate.getId());
            method.setRepaymentMethod(prototypeCondition.getRepaymentMethod());
            method.setRepaymentMethodData(prototypeCondition.getMethodParametersForm().toString());
            productUpdateRepayService.save(method);
        }
        //修改利率
        productUpdateRateService.updateProductPlanRate(prototypeCondition.getPlanRatejson(), productUpdate.getId());

        return new IResponse<ProductUpdate>().setData(productUpdate);
    }

    @PostMapping(value = "/getApprovePlanDetail")
    @ApiOperation(value = "产品方案修改代办任务详情")
    public IResponse getApprovePlanDetail(@RequestBody ProductUpdate approve) {
        ProductUpdate productUpdate = productUpdateService.getOne(Wrappers.<ProductUpdate>query().lambda()
                .eq(ProductUpdate::getId, approve.getId())//根据流程ID查询
                ,false
        );
        return IResponse.success(productUpdate);
    }

    @PostMapping(value = "/queryProductUpdatePlanList")
    @ApiOperation(value = "获取产品方案列表信息")
    public IResponse<ProductUpdatePlanVo> queryProductUpdatePlanList(@RequestBody ProductUpdateCondition condition) {
        //查询产品上线方案数据表
        IPage<List<ProductUpdatePlanVo>> list = productUpdatePlanService.queryProductUpdatePlanList(new Page(condition.getPageNumber(), condition.getPageSize()),condition.getId());
        return IResponse.success(list);
    }


    @PostMapping(value = "/queryProductUpdateList")
    @ApiOperation(value = "产品方案修改代办任务详情")
    public IResponse queryProductUpdateList(@RequestBody QueryCondition<ProductPlanCondition> planCondition) {
        //查询未上线的修改方案
        List<ProductUpdate> productUpdateList = productUpdateService.list(Wrappers.<ProductUpdate>query().lambda()
                .ne(ProductUpdate::getStatus, AfsEnumUtil.key(StatusType.BELAUNCH))//根据状态查询
        );
        //未上线的修改方案ID
        List productUpdateListId = Lists.transform(productUpdateList, (productUpdate) -> {
            return productUpdate.getId();
        });
        //未上线的修改方案对应的产品方案
        List<ProductUpdatePlan> productUpdatePlanList = productUpdatePlanService.list(Wrappers.<ProductUpdatePlan>query().lambda()
                .in(ProductUpdatePlan::getProductUpdateId, productUpdateListId)//根据ID查询
        );
        //产品方案ID
        List productPlanListId = Lists.transform(productUpdatePlanList, (productUpdatePlan) -> {
            return productUpdatePlan.getProductPlanId();
        });

        //状态list
        List listStatus = new ArrayList();
        listStatus.add(AfsEnumUtil.key(ProductOnlineStatus.GO_ONLINE));
//        listStatus.add(AfsEnumUtil.key(ProductOnlineStatus.OFFLINE));

        //未进行修改流程的产品方案
        IPage<List<ProductPlan>> list = null;

        if(productPlanListId.size()>0){
            //查询产品方案
            List<ProductPlan> productPlanList = productPlanService.list(Wrappers.<ProductPlan>query().lambda()
                    .in(ProductPlan::getId, productPlanListId)//根据ID查询
            );
            //产品编号
            String[] productNumberList = new String[productPlanList.size()];
            for(int i =0;i< productPlanList.size();i++){
                ProductPlan productPlan = productPlanList.get(i);
                productNumberList[i] = productPlan.getProductNumber();
            }
            list = productPlanService.page(new Page(planCondition.getPageNumber(), planCondition.getPageSize()), (Wrapper<ProductPlan>) Wrappers.<ProductPlan>query().lambda()
                    .eq(ProductPlan::getTemplateCategory,planCondition.getCondition().getTemplateCategory())
                    .eq(ProductPlan::getProductTemplateId,planCondition.getCondition().getProductTemplateId())
                    .in(ProductPlan::getStatus, listStatus)//状态
                    .notIn(ProductPlan::getProductNumber, productNumberList)//同一产品编号不可查询出来

                    .like(StringUtils.isNotEmpty(planCondition.getCondition().getProductNumber()),ProductPlan::getProductNumber,planCondition.getCondition().getProductNumber())//产品模糊查询
                    .like(StringUtils.isNotEmpty(planCondition.getCondition().getProductName()),ProductPlan::getProductName,planCondition.getCondition().getProductName())//产品模糊查询
                    .eq(StringUtils.isNotEmpty(planCondition.getCondition().getStatus()),ProductPlan::getStatus,planCondition.getCondition().getStatus())//产品模糊查询
            );
        }else{
            list = productPlanService.page(new Page(planCondition.getPageNumber(), planCondition.getPageSize()), (Wrapper<ProductPlan>) Wrappers.<ProductPlan>query().lambda()
                    .eq(ProductPlan::getTemplateCategory,planCondition.getCondition().getTemplateCategory())
                    .eq(ProductPlan::getProductTemplateId,planCondition.getCondition().getProductTemplateId())
                    .in(ProductPlan::getStatus, listStatus)//状态

                    .like(StringUtils.isNotEmpty(planCondition.getCondition().getProductNumber()),ProductPlan::getProductNumber,planCondition.getCondition().getProductNumber())//产品模糊查询
                    .like(StringUtils.isNotEmpty(planCondition.getCondition().getProductName()),ProductPlan::getProductName,planCondition.getCondition().getProductName())//产品模糊查询
                    .eq(StringUtils.isNotEmpty(planCondition.getCondition().getStatus()),ProductPlan::getStatus,planCondition.getCondition().getStatus())//产品模糊查询
            );
        }

        return IResponse.success(list);
    }

    @PostMapping(value = "/saveProductUpdatePlan")
    @ApiOperation(value = "保存产品修改方案信息")
    public IResponse saveProductUpdatePlan(@RequestBody ProductUpdatePlanCondition condition) {
        //循环保存
        for(Long id:condition.getIds()){
            ProductUpdatePlan productUpdatePlan = new ProductUpdatePlan();
            productUpdatePlan.setProductPlanId(id);
            productUpdatePlan.setProductUpdateId(condition.getId());
            productUpdatePlanService.save(productUpdatePlan);
        }
        return IResponse.success(true);
    }

    @RequestMapping(value = "/delUpdatePlanById/{id}", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除产品上线方案计划信息")
    @Transactional(rollbackFor = Exception.class)
    public IResponse delUpdatePlanById(@PathVariable String id) {
        //查询
        ProductUpdatePlan updatePlan = productUpdatePlanService.getById(id);
        //判断
        if (updatePlan == null)
            return IResponse.fail("所选的产品方案已被删除了");
        //删除
        productUpdatePlanService.removeById(updatePlan);
        return IResponse.success(true);
    }

    @RequestMapping(value = "/delUpdateById/{id}", method = RequestMethod.DELETE)
    @ApiOperation(value = "删除产品上线信息")
    @Transactional(rollbackFor = Exception.class)
    public IResponse delUpdateById(@PathVariable Long id) {

        //查询产品修改方案
        ProductUpdate productUpdate = productUpdateService.getById(id);

        //删除产品修改方案
        productUpdatePlanService.remove(Wrappers.<ProductUpdatePlan>query().lambda()
                .eq(ProductUpdatePlan::getProductUpdateId, productUpdate.getId())
        );
        //删除产品修改原子
        productUpdateAtomService.remove(Wrappers.<ProductUpdateAtom>query().lambda()
                .eq(ProductUpdateAtom::getProductUpdateId, productUpdate.getId())
        );
        //删除产品修改利率
        productUpdateRateService.remove(Wrappers.<ProductUpdateRate>query().lambda()
                .eq(ProductUpdateRate::getProductUpdateId, productUpdate.getId())
        );
        //删除产品修改还款方式
        productUpdateRepayService.remove(Wrappers.<ProductUpdateRepay>query().lambda()
                .eq(ProductUpdateRepay::getProductUpdateId, productUpdate.getId())
        );
        //删除修改方案
        productUpdateService.removeById(productUpdate);
        return IResponse.success(true);
    }

    @SneakyThrows
    @PostMapping("/processSubmission")
    @ApiOperation(value = "发起流程")
    @Transactional(rollbackFor = Exception.class)
    public IResponse<ProductUpdate> processSubmission(@RequestBody ProductUpdateCondition condition) {

        List<ProductUpdatePlan> productUpdatePlanList = productUpdatePlanService.list(Wrappers.<ProductUpdatePlan>query().lambda()
                .in(ProductUpdatePlan::getProductUpdateId, condition.getId())//根据ID查询
        );
        if(productUpdatePlanList.size()==0){
            return IResponse.fail("请添加修改的产品方案！");
        }

        //查询
        ProductUpdate updatePlan = productUpdateService.getById(condition.getId());
        updatePlan.setStatus(AfsEnumUtil.key(StatusType.INREVIEW));
        productUpdateService.updateById(updatePlan);

        //发起流程
        /** 1、组装流程实例 */
        StartFlowRequest startFlowNew = new StartFlowRequest();
        startFlowNew.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.PRODUCT_MODIFY));//塞入afs内部映射key
        startFlowNew.setFlowName((StringUtils.isEmpty(updatePlan.getPlanName())?"":(updatePlan.getPlanName())+"-")+AfsEnumUtil.desc(WorkflowTypeEnum.PRODUCT_MODIFY));//塞入流程名称
        startFlowNew.setBizDataId(updatePlan.getId().toString());//业务主键
        /** 2、组装业务数据 */
        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(updatePlan);
        JSONObject cancelJson = JSONObject.parseObject(json);
        /** 3、正式发起流程 */
        workflowService.startWorkFlow(startFlowNew, cancelJson);

        return IResponse.success(true);
    }

    @SneakyThrows
    @PostMapping(value = "/submitApproveProcess")
    @ApiOperation(value = "提交修改流程审批信息")
    @Transactional
    public IResponse submitApproveProcess(@RequestBody ProductUpdateCondition condition) {
        //根据ID查询修改主表
        ProductUpdate productUpdate = productUpdateService.getById(condition.getId());
        //推进流程
        WorkTaskAssign assgin = workTaskAssignService.getOne(Wrappers.<WorkTaskAssign>query().lambda()
                .eq(WorkTaskAssign::getBizDataId, productUpdate.getId().toString())
                .eq(WorkTaskAssign::getUserName, SecurityUtils.getUsername())
        );
        WorkTaskCreated created = workTaskCreatedService.getOne(Wrappers.<WorkTaskCreated>query().lambda()
                .eq(WorkTaskCreated::getBizDataId, productUpdate.getId().toString())
        );
        //提交完成之后删除其他人员代办
        List<WorkTaskAssign> assignList = workTaskAssignService.list(Wrappers.<WorkTaskAssign>query().lambda()
                .eq(WorkTaskAssign::getBizDataId, productUpdate.getId().toString())
        );
        TaskSubmitRequest taskSubmitRequest = new TaskSubmitRequest();
        taskSubmitRequest.setGwtUserId(assgin.getAssignId());
        taskSubmitRequest.setAfsFlowKey(created.getAfsFlowKey());
        taskSubmitRequest.setBizDataId(productUpdate.getDataId() + "");
        QueryFLowCmdRequest request = new QueryFLowCmdRequest();
        request.setFlowInstanceId(created.getFlowInstanceId());
        WorkFlowResponse<List<FlowCmdBean>> cmdResponse = workflowService.queryFlowCmd(request);
        List<FlowCmdBean> cmdList = cmdResponse.getAfsData();
        FlowCmdBean cmd = workTaskCreatedService.channelApprove(condition.getApproveSuggest(), cmdList);
        if (cmd != null) {
            log.info("==================================提交工作流开始==================================》");
            taskSubmitRequest.setCmdId(cmd.getId());
            ObjectMapper mapper = new ObjectMapper();
            //获取配置节点信息
            String json = mapper.writeValueAsString(productUpdate);
            JSONObject cancelJson = JSONObject.parseObject(json);
            workflowService.taskSubmit(taskSubmitRequest, cancelJson);

            //删除剩余节点数据信息
            for (int i = 0; i < assignList.size(); i++) {
                workTaskAssignService.removeById(assignList.get(i).getId().toString());
            }

            //保存审批记录
            WorkApproveRecord record = new WorkApproveRecord();
            record.setApproveSuggest(condition.getApproveSuggest());//审批意见
            record.setApproveRemark(condition.getApprovalRemarks());//审批备注
            record.setDisposeNode(created.getNodeId());//审批节点
            record.setDisposeNodeName(created.getTaskName());//节点名称
            record.setDisposeStaff(SecurityUtils.getUsername());//审批人员
            record.setApproveEndTime(DateUtil.date());//审批结束时间
            record.setProductNo(productUpdate.getId().toString());//审批编号
            record.setUseScene(AfsEnumUtil.key(WorkflowTypeEnum.PRODUCT_MODIFY));//审批场景
            record.setStageId(productUpdate.getId());//流程实例ID
            workApproveRecordService.save(record);

        }

        if (condition.getIsFinalJudgment() && AfsEnumUtil.key(WorkflowTypeEnum.SUBMIT).equals(condition.getApproveSuggest())) {
            productUpdateService.update((Wrappers.<ProductUpdate>lambdaUpdate()
                    .eq(ProductUpdate::getId, condition.getId())
                    .set(ProductUpdate::getStatus, AfsEnumUtil.key(StatusType.TOREVIEW))
            ));
        } else {
            productUpdateService.update((Wrappers.<ProductUpdate>lambdaUpdate()
                    .eq(ProductUpdate::getId, condition.getId())
                    .set(ProductUpdate::getStatus, AfsEnumUtil.key(StatusType.INREVIEW))
            ));
        }

        return IResponse.success("流程提交成功！");
    }


}
